<html>
    <head>
        <title>全局功能  Global Features</title>
    </head>
    <body>
        <script>
            //  全局功能

                /*
                    全局功能系统用于"在开发时"启用/禁用应用程序功能。

                    它是在开发时完成的，因为一些服务 (例如控制器)已经从应用程序模型中删除，且数据库表不会为禁用的功能创建，这在运行时是不可能的。

                    如果你想开发具有可选功能的可重用应用程序模块，全局功能系统特别有用。如果最终应用程序不想使用某些功能，它可以禁用这些功能。
                */

                /*
                    一、安装

                        默认情况下，此软件包已与启动模板一起安装。所以，大多数时候，你不需要手动安装它。

                        在项目文件夹（. csproj文件）中打开命令行窗口并键入以下命令：

                            abp add-package Volo.Abp.GlobalFeatures
                */

                /*
                    二、定义全局功能    Defining a Global Feature 

                        全局功能类是这样的：

                            public class MyGlobalFeature : GlobalFeature
                            {
                                public MyGlobalFeature()
                                {
                                    //...
                                }
                            }
                */

                /*
                    三、启用/禁用全局功能  

                                
                        1、启用/禁用全局功能:

                                使用GlobalFeatureManager.Istance 启用/禁用全局功能。

                                    //  通过Enable/Disabel 方法的泛型参数来启用/禁用全局功能。
                                    GlobalFeatureManager.Instance.Enable<PaymentFeature>();
                                    GlobalFeatureManager.Instance.Disable<PaymentFeature>();

                                    // 通过功能名称来启用/禁用全局功能。
                                    GlobalFeatureManager.Instance.Enable("Shopping.Payment");
                                    GlobalFeatureManager.Instance.Disable("Shopping.Payment");

                                    除非明确启用全局功能，否则将禁用它们。



                        2、在哪里配置全局共功能？

                                全局功能必须在应用程序启动前配置。由于 GlobalFeatureManager.Instance 是"单例对象"，一次性、静态配置就足够了。

                                建议在模块的 PreConfigureServices方法中启用/禁用全局功能.

                                你可以使用 OneTimeRunner (工具类)来确保它只能运行一次。

                                        private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();

                                        // 在PreConfigureServices方法中启用全局功能
                                        public override void PreConfigureServices(ServiceConfigurationContext context)
                                        {
                                            OneTimeRunner.Run(() =>  // 保证只运行一次
                                            {
                                                GlobalFeatureManager.Instance.Enable<PaymentFeature>();
                                            });
                                        }
                */


                /*
                    四、检查全局功能


                        1、使用 GlobalFeatureManager.Istance 检查全局功能。
                                同样，检查全局功能也使用GlobalFeatureManager.Istance：

                                        GlobalFeatureManager.Instance.IsEnabled<PaymentFeature>();
                                        GlobalFeatureManager.Instance.IsEnabled("Shopping.Payment");

                                两种方法都返回bool。因此，你可以编写如下所示的条件逻辑：
                                        
                                        if (GlobalFeatureManager.Instance.IsEnabled<PaymentFeature>())
                                        {
                                            // Some strong payment codes here...
                                        }

                        2、使用 [RequiresGlobalFeature]特性检查全局功能

                                除了手动检查之外，还有[RequiresGlobalFeature]属性用于以声明方式检查控制器或页面。
                                
                                如果相关功能被禁用，ABP返回HTTP Response404。

                                            [RequiresGlobalFeature(typeof(PaymentFeature))]
                                            public class PaymentController : AbpController
                                            {

                                            }

                */

                /*
                    五、对模块的全局功能进行分组

                                对模块的全局功能进行分组以允许最终应用程序开发人员轻松发现 和 配置功能是很常见的。

                                以下示例显示了如何对模块的功能进行分组。

                                假设我们已经为Ecommerce模块的Subscription功能定义了一个全局特性：

                                            [GlobalFeatureName("Ecommerce.Subscription")]
                                            public class SubscriptionFeature : GlobalFeature
                                            {
                                                public SubscriptionFeature(GlobalModuleFeatures module)
                                                    : base(module)
                                                {
                                                }
                                            }

                                你可以在模块中定义任何数量的全局功能。然后定义一个类将这些功能组合在一起：

                                            public class GlobalEcommerceFeatures : GlobalModuleFeatures // 模块功能分组基类
                                            {
                                                public const string ModuleName = "Ecommerce"; // 模块名称

                                                public SubscriptionFeature Subscription => GetFeature<SubscriptionFeature>();
                                                
                                                public GlobalEcommerceFeatures(GlobalFeatureManager featureManager)
                                                    : base(featureManager)
                                                {
                                                    AddFeature(new SubscriptionFeature(this));
                                                }
                                            }
                                            
                                最后，你可以在GlobalModuleFeaturesDictionary上创建一个扩展方法：

                                            public static class GlobalModuleFeaturesDictionaryEcommerceExtensions
                                            {
                                                public static GlobalEcommerceFeatures Ecommerce(
                                                    this GlobalModuleFeaturesDictionary modules)
                                                {
                                                    return modules.GetOrAdd(
                                                        GlobalEcommerceFeatures.ModuleName,
                                                        _ => new GlobalEcommerceFeatures(modules.FeatureManager)
                                                    ) as GlobalEcommerceFeatures;
                                            }

                                然后GlobalFeatureManager.Instance.Modules.Ecommerce()可用于访问模块的全局功能。示例用法：
                                                
                                            GlobalFeatureManager.Instance.Modules.Ecommerce().Subscription.Enable();
                                            GlobalFeatureManager.Instance.Modules.Ecommerce().EnableAll();
                */
        </script>
    </body>
</html>